﻿/*----------------------------------------------------------------------------------------------
*
* This file is XIUSDK's property. It contains XIUSDK's trade secret, proprietary and
* confidential information.
*
* The information and code contained in this file is only for authorized XIUSDK employees
* to design, create, modify, or review.
*
* DO NOT DISTRIBUTE, DO NOT DUPLICATE OR TRANSMIT IN ANY FORM WITHOUT PROPER AUTHORIZATION.
*
* If you are not an intended recipient of this file, you must not copy, distribute, modify,
* or take any action in reliance on it.
*
* If you have received this file in error, please immediately notify XIUSDK and
* permanently delete the original and any copy of any file and any printout thereof.
*
*---------------------------------------------------------------------------------------------*/
/*****************************************************************************
 Copyright:    www.xiusdk.cn(all rights reserved)
 Description:  beautyEngine sdk 包含人脸美化模块/滤镜模块
 Author:       xiusdk
 Version:      V1.2
 qq group:     567648913(加群获取最新信息)
*****************************************************************************/
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using UnityEngine;

namespace Xiu
{
    class BeautyEngine : IDisposable
    {

        // 必须调用
        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.None, ExactSpelling = true)]
        private static extern IntPtr Beauty_InitBeautyEngine(String filePath);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_UninitBeautyEngine(IntPtr handle);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern int Beauty_ProcessBuffer(IntPtr handle, IntPtr srcData, int width, int height, int stride);


        // 可选择调用
        //#define PIXELFORMAT_BGRA   0  // 
        //#define PIXELFORMAT_RGBA   1  // 
        //#define PIXELFORMAT_NV21   2  // yyyy vu
        //#define PIXELFORMAT_NV12   3  // yyyy uv
        //#define PIXELFORMAT_I420   4  // yyyy u v
        //#define PIXELFORMAT_YV12   5  // yyyy v u
        //#define PIXELFORMAT_I422   6  // yyyy uu vv
        //#define PIXELFORMAT_YV16   7  // yyyy vv uu
        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetPixelFMT(IntPtr handle, int pixFMT);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetFacePoints(IntPtr handle, int faceCount, int[] points);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_ClearParams(IntPtr handle);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetSoftenRatio(IntPtr handle, int softenRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetWhitenRatio(IntPtr handle, int writenRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetFilterID(IntPtr handle, int filterID);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetFilterRatio(IntPtr handle, int filterRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetSkinDetectionEnable(IntPtr handle, int skinDetectionEnable);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetDefreckleAutoEnable(IntPtr handle, int defreckleAutoEnable);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetEyeBagRemoveRatio(IntPtr handle, int eyeBagRemoveRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetLightEyeRatio(IntPtr handle, int lightEyeRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetEyeWarpRatio(IntPtr handle, int eyeWarpRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetFaceLiftRatio(IntPtr handle, int faceLiftRatio);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetLipsColorRatio(IntPtr handle, int lipsColorRatio);

        // lipsColor[3]
        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetLipsColor(IntPtr handle, int[] lipsColor);

        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetHighnoseRatio(IntPtr handle, int highnoseRatio);


        // defrecklePosition[2]
        [DllImport("XIUSDK_BeautyEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern void Beauty_SetDefreckleMenualRadiusAndPosition(IntPtr handle, int defreckleRadius, int[] defrecklePosition);


        private IntPtr instance = IntPtr.Zero;

        public BeautyEngine()
        {
            //int gray
            String filePath = Application.dataPath;
            instance = Beauty_InitBeautyEngine(filePath);
        }

        ~BeautyEngine()
        {
            Dispose();
        }

        public void Dispose()
        {
            if (instance != IntPtr.Zero)
            {
                Beauty_UninitBeautyEngine(instance);
                instance = IntPtr.Zero;
            }
        }


        public Bitmap BeautyProcess(Bitmap src, int whitenRatio, int softRatio, int filterId, int filterRatio, int facenum, int[] featurePoints, int faceLiftRatio, int eyeWarpRatio, int lightEyeRatio)
        {
            Bitmap a = new Bitmap(src);
            int w = a.Width;
            int h = a.Height;
            BitmapData srcData = a.LockBits(new Rectangle(0, 0, a.Width, a.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); //Format32bppArgb
            int stride = srcData.Stride;
            Beauty_ClearParams(instance);
            Beauty_SetSoftenRatio(instance, softRatio);
            Beauty_SetWhitenRatio(instance, whitenRatio);
            Beauty_SetFilterID(instance, filterId);
            Beauty_SetFilterRatio( instance, filterRatio);

            if (facenum > 0)
            {
                Beauty_SetFacePoints(instance, 1, featurePoints);

                //eyewarp
                Beauty_SetEyeWarpRatio(instance, eyeWarpRatio);

                // facelift
                Beauty_SetFaceLiftRatio(instance, faceLiftRatio);

                // lighteye
                Beauty_SetLightEyeRatio(instance, lightEyeRatio);

                // colorlips
                int[] lipsColor = new int[3] { 255, 0, 0 };
                int lipsRatio = 50;
                Beauty_SetLipsColorRatio(instance, lipsRatio);
                Beauty_SetLipsColor(instance, lipsColor);
            }

            Beauty_ProcessBuffer(instance, srcData.Scan0, w, h, stride);

            a.UnlockBits(srcData);
            return a;
        }

        public Texture2D BeautyTexture(Texture2D src, int whitenRatio, int softRatio, int filterId, int filterRatio, int facenum, int[] featurePoints, int faceLiftRatio, int eyeWarpRatio, int lightEyeRatio)
        {
            MemoryStream source = new MemoryStream(src.EncodeToJPG());
            Bitmap bitmap = (Bitmap)System.Drawing.Image.FromStream(source);
            Bitmap result = BeautyProcess(bitmap, whitenRatio, softRatio, filterId, filterRatio, facenum, featurePoints, faceLiftRatio, eyeWarpRatio, lightEyeRatio);
            bitmap.Dispose();
            MemoryStream target = new MemoryStream();
            result.Save(target, System.Drawing.Imaging.ImageFormat.Jpeg);
            Texture2D dest = new Texture2D(result.Width, result.Height);
            dest.LoadImage(target.ToArray());
            return dest;
        }



    }
}
